package org.linlinjava.litemall.core.util;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class OssUtil {
	
	/**
	 * 基础配置
	 */
	private final static String ACCESS_KEY_ID = "LTAI4FcYGTDfTjRbbchGB4Td";
	private final static String ACCESS_KEY_SECRET = "pzZ4dtZWzHDR1hCTJiMACMLIzksjG4";
	private final static String BUCKET_NAME = "tianbwpdf";
	private final static String ENDPOINT = "oss-cn-hangzhou.aliyuncs.com";
	private final static String fileName = "23fekb48lccjk62w1r8l.png";

	private static OSS client = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

	public static boolean deleteFile(String filePath) {

		boolean exist = client.doesObjectExist(BUCKET_NAME, filePath);
		if (exist) {

			client.deleteObject(BUCKET_NAME, filePath);
			client.shutdown();

			return true;
		}
return false;
	}


	public static void text(){
		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(new File("C:/pdf/12345.png"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		client.putObject(BUCKET_NAME, fileName, inputStream);
	}


	/**
	 * 简单文件上传
	 *
	 * @param file     文件
	 * @param fileName 文件名
	 * @return 返回结果
	 */
	public static String simpleUpload( ) {
		
		client.putObject(new PutObjectRequest(BUCKET_NAME, fileName, new File("C:/pdf/12345.png")));
		boolean b = client.doesObjectExist(BUCKET_NAME, fileName);
		//官方文档没找到特别好的返回外网URL地址的方法，虽然有一个client.generatePresignedUrl()方法，但这个方法必须传入过期时间。如果有更好的实现，欢迎留言告知。谢谢~
		return b ? "http://" + BUCKET_NAME + "." + ENDPOINT + "/" + "123.pdf" : "";
	}
	
	/**
	 * 断点续传上传
	 *
	 * @param filePath 文件路径
	 * @param fileName 文件名
	 * @return 返回结果
	 */
	public static String breakpointUpload(String filePath, String fileName) {
		
		try {
			UploadFileRequest uploadFileRequest = new UploadFileRequest(BUCKET_NAME, fileName);
			// 本地文件上传---文件必须存在
			uploadFileRequest.setUploadFile(filePath);
			// 设置5个上传任务
			uploadFileRequest.setTaskNum(5);
			// 设置每个部分为1M
			uploadFileRequest.setPartSize(1024 * 1024);
			// 启动文件节点检查，默认是false
			uploadFileRequest.setEnableCheckpoint(true);
			
			UploadFileResult uploadResult = client.uploadFile(uploadFileRequest);
			
			CompleteMultipartUploadResult multipartUploadResult = uploadResult.getMultipartUploadResult();

		} catch (OSSException oe) {

		} catch (ClientException ce) {

		} catch (Throwable throwable) {
			throwable.printStackTrace();
		}
		boolean b = client.doesObjectExist(BUCKET_NAME, fileName);
		return b ? "http://" + BUCKET_NAME + "." + ENDPOINT + "/" + fileName : "";
	}
	
	/**
	 * 带进度条的上传(根据需求改造，建议使用redis做缓存)
	 *
	 * @param file     文件
	 * @param fileName 文件名
	 * @return 返回结果
	 */
/*	public static String progressUpload(File file, String fileName) {
		
		try {
			PutObjectResult putObjectResult = client.putObject(new PutObjectRequest(BUCKET_NAME, fileName, file).withProgressListener(new GetProgressUtil.PutObjectProgressListener()));

			
		} catch (OSSException oe) {

		} catch (ClientException ce) {

		}
		boolean b = client.doesObjectExist(BUCKET_NAME, fileName);
		return b ? "http://" + BUCKET_NAME + "." + ENDPOINT + "/" + fileName : "";
	}
	*/
	/**
	 * 追加上传
	 * 文件的第一次上传，需第一次将位置设置为零: long firstPosition = 0L;
	 *
	 * @param file     文件
	 * @param fileName 文件名
	 * @return 返回结果
	 */
	public static long appendObject(File file, String fileName, long position) {
		
		AppendObjectResult appendObjectResult = new AppendObjectResult();
		try {
			appendObjectResult = client.appendObject(new AppendObjectRequest(BUCKET_NAME, fileName, file).withPosition(position));
		} catch (OSSException oe) {

		} catch (ClientException ce) {

		}
		return appendObjectResult.getNextPosition();
	}




	/**
	 * 文件删除
	 *
	 * @param fileName 文件名
	 * @return 返回结果
	 */
	public static List<String> deleteObject() {
		
		List<String> deletedObjects = new ArrayList<>();
		try {
			List<String> keys = new ArrayList<>();
			keys.add(fileName);
			//删除单个文件无返回类型，所以选择删除list获取返回值的方式进行删除
			DeleteObjectsResult deleteObjectsResult = client.deleteObjects(
					new DeleteObjectsRequest(BUCKET_NAME).withKeys(keys));
			deletedObjects = deleteObjectsResult.getDeletedObjects();
			
		} catch (OSSException oe) {

		} catch (ClientException ce) {

		}
		return deletedObjects;
	}
	
	/**
	 * 下载到本地文件
	 * 流式下载（https://help.aliyun.com/document_detail/84823.html?spm=a2c4g.11186623.6.724.71bc3359mGbCFN）
	 *
	 * @param fileName 文件名
	 * @return 操作状态
	 */
	public static boolean getObject() {
		boolean result = false;
		try {

			File targetFile = new File("C:/pdf/1.png");

			if (!targetFile.getParentFile().exists()) {
				targetFile.getParentFile().mkdirs();
			}
			 client.getObject(new GetObjectRequest(BUCKET_NAME, fileName),
					 targetFile);

			result = true;

		} catch (OSSException oe) {

		} catch (Exception ce) {

		}
		return result;
	}
	
	/**
	 * 分片上传
	 *
	 * @param file     文件
	 * @param fileName 文件名
	 * @return 返回结果
	 */
/*	public static String multipartUpload(File file, String fileName, long partSize) {
		ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("multipart-upload-pool-%d").build();
		ExecutorService executorService = new ThreadPoolExecutor(4, 16, 0L,
				TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(10240), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
		try {
			String uploadId = claimUploadId(fileName);
			long fileLength = file.length();
			int partCount = (int) (fileLength / partSize);
			if (fileLength % partSize != 0) {
				partCount++;
			}
			if (partCount > 10000) {
				throw new RuntimeException("Total parts count should not exceed 10000");
			} else {
				log.info("Total parts count " + partCount + "\n");
			}
			List<Future<PartETag>> futures = new ArrayList<>();
			for (int i = 0; i < partCount; i++) {
				long startPos = i * partSize;
				long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
				int partNumber = i + 1;
				Callable<PartETag> run = () -> {
					InputStream inputStream = new FileInputStream(file);
					long skip = inputStream.skip(startPos);
					log.info("inputStream skip: {}", skip);
					UploadPartRequest uploadPartRequest = new UploadPartRequest();
					uploadPartRequest.setBucketName(BUCKET_NAME);
					uploadPartRequest.setKey(fileName);
					uploadPartRequest.setUploadId(uploadId);
					uploadPartRequest.setInputStream(inputStream);
					uploadPartRequest.setPartSize(curPartSize);
					uploadPartRequest.setPartNumber(partNumber);
					UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
					log.info("Part#" + partNumber + " done\n");
					return uploadPartResult.getPartETag();
				};
				futures.add(executorService.submit(run));
			}
			
			*//*
			 * 等待全部上传后关闭线程池
			 *//*
			executorService.shutdown();
			while (!executorService.isTerminated()) {
				try {
					executorService.awaitTermination(5, TimeUnit.SECONDS);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			if (futures.size() != partCount) {
				throw new IllegalStateException("Upload multiparts fail due to some parts are not finished yet");
			} else {
				log.info("Succeed to complete multiparts into an object named " + fileName + "\n");
			}
			
			//查错时可以使用
//			listAllParts(uploadId, fileName);
			completeMultipartUpload(uploadId, fileName, futures);
			
		} catch (OSSException oe) {
			printOSSException(oe);
		} catch (ClientException ce) {
			printClientException(ce);
		}
		boolean b = client.doesObjectExist(BUCKET_NAME, fileName);
		return b ? "http://" + BUCKET_NAME + "." + ENDPOINT + "/" + fileName : "";
	}*/
	
	/**
	 * 声明uploadId
	 *
	 * @param fileName 文件名
	 * @return uploadId
	 */
	private static String claimUploadId(String fileName) {
		InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, fileName);
		InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
		return result.getUploadId();
	}
	
	/**
	 * 将上传的碎片整理成一个文件
	 *
	 * @param uploadId 上传id
	 * @param fileName 文件名
	 * @param futures  callable返回值
	 */
/*	private static void completeMultipartUpload(String uploadId, String fileName, List<Future<PartETag>> futures) {
		List<PartETag> partETags = new ArrayList<>();
		for (Future<PartETag> future : futures) {
			try {
				if (future.get() != null) {
					partETags.add(future.get());
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		partETags.sort(Comparator.comparingInt(PartETag::getPartNumber));
		
		log.info("Completing to upload multiparts\n");
		CompleteMultipartUploadRequest completeMultipartUploadRequest =
				new CompleteMultipartUploadRequest(BUCKET_NAME, fileName, uploadId, partETags);
		client.completeMultipartUpload(completeMultipartUploadRequest);
	}*/
	
	/**
	 * 列出全部已上传的部分
	 *
	 * @param uploadId 上传id
	 * @param fileName 文件名
	 */
/*	private static void listAllParts(String uploadId, String fileName) {
		log.info("Listing all parts......");
		ListPartsRequest listPartsRequest = new ListPartsRequest(BUCKET_NAME, fileName, uploadId);
		PartListing partListing = client.listParts(listPartsRequest);
		
		int partCount = partListing.getParts().size();
		for (int i = 0; i < partCount; i++) {
			PartSummary partSummary = partListing.getParts().get(i);
			log.info("\tPart#" + partSummary.getPartNumber() + ", ETag=" + partSummary.getETag());
		}
	}*/
	
	/**
	 * OSSException异常打印
	 *
	 * @param oe OSSException
	 */
/*	private static void printOSSException(OSSException oe) {
		log.info("Caught an OSSException, which means your request made it to OSS, "
				+ "but was rejected with an error response for some reason.");
		log.info("Error Message: " + oe.getErrorCode());
		log.info("Error Code:       " + oe.getErrorCode());
		log.info("Request ID:      " + oe.getRequestId());
		log.info("Host ID:           " + oe.getHostId());
	}
	*/
	/**
	 * ClientException异常打印
	 *
	 * @param ce ClientException
	 */

	
	
	/**
	 * @return 创建一个temp文件 -- 测试使用
	 * @throws IOException 异常
	 */
/*	private static File createTempFile() throws IOException {
		File file = File.createTempFile(SerialNumberMaker.getSerialNumberByUUId("F"), ".txt");
		file.deleteOnExit();
		
		Writer writer = new OutputStreamWriter(new FileOutputStream(file));
		for (int i = 0; i < 1000000; i++) {
			writer.write("abcdefghijklmnopqrstuvwxyz\n");
			writer.write("0123456789011234567890\n");
		}
		writer.close();
		
		return file;
	}
	*/
	public static void main(String[] args) throws IOException {

		boolean b = deleteFile("3f99320e-5cb1-47fb-acc0-d20fa10be914.png");
		System.out.println(b);


		//System.out.println(simpleUpload());
		//getObject();
		//simpleUpload();
		//text();
//		File file = createTempFile();
//		String s = simpleUpload(file, file.getName());
//		log.info(s);

//		long l = appendObject(file, file.getName(), 0L);
//		log.info("l: " + l);
//		long l1 = appendObject(file, file.getName(), l);
//		log.info("l1: " + l1);

//		List<String> strings = deleteObject(file.getName());
//		log.info(strings.toString());

//		String filePath = "C:\\Users\\dell\\Desktop\\1.png";
//		String fileName = SerialNumberMaker.getSerialNumberByUUId("F") + "1.png";
//		String s1 = breakpointUpload(filePath, fileName);
//		log.info(s1);

//		final File file = createTempFile();
//		final long partSize = 5 * 1024 * 1024L;
//		String r = multipartUpload(file, file.getName(), partSize);
//		log.info(r);
		//String filenameZip="E:\\test\\test.zip";
//		File file = new File("C:/pdf/1.png")	;
//		if(file.exists()){
//			file.delete();//删除文件
//
//		}

	}
}
